Kotlin Scope Functions
let, run, with, apply, also
関数なんだけど、動作の具体的なものは何も決まってない。
引数に関数(lambda)を取る。それを実行するだけ。
だけど、そのlambdaを実行する際のスコープを便利なように変更してる
this, 仮引数、返却値。その替え方によって、let, run, with, apply, alsoがある
効用として、コードがすっきりし、可読性が向上するので、積極的に利用したい。
目を通しておくと良いもの
連想として、自分にとってなじみがあるもの
python や VBEの with
javascriptの callやapplyのような感じ?
が、Kotlinのものは包括的になっていて、理解が追いついていない。code readingに必要 最後の評価を返す: (R = 単一式)になってる
let public inline fun <T, R> T.let(f: (T) -> R): R = f(this)
it で引数をとり、最後の評価を返す。
nullableに対して、操作をしたい時に、if(hoge==null)...は、冗長。コードが膨れるので、
hoge?.let{ it.doSomething() } として 1つの式にできる
run public inline fun <T, R> T.run(f: T.() -> R): R = f()
thisを使う。最後の評価を返す
with public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
(拡張関数ではなく、対象のものを引数とって、次にlambda. (引数の最後が関数の場合はfoo(){} と書ける)
他の言語のwithと同じイメージ。 用法はrunとほぼ同じ?で、runのがしっくりくるかも。
レシーバーをそのまま戻す: :T {....; return this}の形
apply public inline fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
applyは引数として受け取った関数を実行して何か仕事をしますが、返す値はレシーバだからです
withに return this が機能付与されたもの
also public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
applyだと this が変わってしまうので、レシーバーは itにしておきたい(もしくはパラメータに名前つけられる)。
で、thisはalsoの内と外で変わらない。
scope自体は変わらないと言える?
code: also.kt
val a = Some()
doSomethind(a)
これを、Some().also{doSomething(it)} と書ける。変数が減り、行数が減る。可読性が上がる。
doSomething(Some())でよいのでは? 左から右に順番に流れるのが大事?
Some() (this, レシーバーが) がreturnされるので、chainしやすい。
代入式を書いてる時に, あっとなって、.also{} つけても、代入される値が変わらないのがよいかも。
thisを{}で変化させることはできるが、、
takeif